package com.servoy.r3.plugins;

import java.io.File;
import java.io.StringWriter;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

import com.servoy.j2db.util.Debug;

public class XMLSampleData {

	public final static String XML_ROOTTAG = "SAMPLEDATA";
	public final static String XML_REPORTTAG = "REPORT";
	public final static String XML_ROWTAG = "ROW";

	public final static String XML_REPORTTAG_NAME_ATTRIBUTE = "Name";

	public final static String XML_ROWXPATH1 = "/" + XML_ROOTTAG + "/"
			+ XML_REPORTTAG + "[@" + XML_REPORTTAG_NAME_ATTRIBUTE + "=" + "'";

	public final static String XML_ROWXPATH2 = "']/" + XML_ROWTAG;

	public final static int ALLROWSVALUE = -1;

	private Element root;
	private Document xmldoc;

	public XMLSampleData() {

		try {
			// Create the xml document.
			DocumentBuilderFactory fct = DocumentBuilderFactory.newInstance();
			DocumentBuilder dbuilder = fct.newDocumentBuilder();
			DOMImplementation impl = dbuilder.getDOMImplementation();
			xmldoc = impl.createDocument(null, XML_ROOTTAG, null);

			root = xmldoc.getDocumentElement();
		} catch (DOMException dex) {
			Debug.error(dex);
		} catch (Exception ex) {
			Debug.error(ex);
		}
	}

	public void createRaportData(ResultSet rs, int rows, String filename) {

		try {

			ResultSetMetaData rsmd = rs.getMetaData();

			String encname = Base64.encodeObject(Utils
					.getNameWithoutExtensionFromFileName(filename),
					Base64.URL_SAFE);

			Element raport1 = xmldoc.createElement(XML_REPORTTAG);
			raport1.setAttribute(XML_REPORTTAG_NAME_ATTRIBUTE, encname);

			// Fill the document
			Element elrow = null;
			Element elcol = null;
			int pos = 0;
			while (rs.next()) {
				if (rows > ALLROWSVALUE)
					if (pos >= rows)
						break;

				elrow = xmldoc.createElement(XML_ROWTAG);

				int colCount = rsmd.getColumnCount();

				for (int i = 1; i < colCount + 1; i++) {
					String colName = rsmd.getColumnName(i);
					// String colClass = rsmd.getColumnClassName(i);

					elcol = xmldoc.createElement(colName);
					// elcol.setAttribute("TYPE", colClass);
					String coltext = rs.getString(i);
					if (coltext == null)
						coltext = "";
					Text n = xmldoc.createTextNode(coltext);

					elcol.appendChild(n);
					elrow.appendChild(elcol);
				}

				raport1.appendChild(elrow);

				pos++;
			}

			root.appendChild(raport1);
		} catch (DOMException dex) {
			Debug.error(dex);
		} catch (Exception ex) {
			Debug.error(ex);
		}
	}

	public String serializeData(String destinationfilename) {
		String result = null;

		try {
			// Serialize the doc
			StringWriter stre = new StringWriter();
			Source domSource = new DOMSource(xmldoc);
			Result streamResult = new StreamResult(stre);
			TransformerFactory tf = TransformerFactory.newInstance();
			tf.setAttribute("indent-number", new Integer(2));
			Transformer serializer = tf.newTransformer();
			serializer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
			serializer.setOutputProperty(OutputKeys.INDENT, "yes");
			serializer.setOutputProperty(
					"{http://xml.apache.org/xslt}indent-amount", "2");

			serializer.transform(domSource, streamResult);

			result = stre.toString();

			// Serialize to file if the parameter is not null
			if (destinationfilename != null) {
				File file = new File(destinationfilename);
				Result fileResult = new StreamResult(file);
				serializer.transform(domSource, fileResult);
			}
		} catch (DOMException dex) {
			Debug.error(dex);
		} catch (Exception ex) {
			Debug.error(ex);
		}

		return result;
	}
}
